﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using JWFW.DAL;

namespace JWFW.Model.CreateCode
{
    /// <summary>
    /// 可以生成BaseEntity和BaseConfigEntity的类代码
    /// </summary>
    public class EntityAutoCreator
    {
        public EntityAutoCreator()
        {
        }

        protected string m_connStr = "";
        protected EDBType m_dbType = EDBType.SimpleSQL;
        protected string m_tableName = "";
        protected string m_className = "";
        protected string m_nameSpace = "BRL";

        protected bool m_hasCode = false;
        protected bool m_cacheTable = false;
        protected int m_cacheObject = 0;
        protected IDBOP m_db = null;
        protected Dictionary<string, string> m_notSetColumn = null;
        protected Dictionary<string, string> m_setColumn = null;
        protected string[] m_fix = new string[] { "id", "name", "comment", "guid", "ts" };


        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnStr
        {
            get { return m_connStr; }
            set
            {
                if (value.Trim() != "")
                {
                    m_connStr = value;
                    this.InitDB();
                }
            }
        }
        /// <summary>
        /// 数据库类型
        /// </summary>
        public EDBType DBType
        {
            get { return m_dbType; }
            set
            {
                m_dbType = value;
                this.InitDB();
            }
        }
        /// <summary>
        /// 实体对应的表名，当类名没有设定时，使用表名最为类名
        /// </summary>
        public string TableName
        {
            get { return m_tableName; }
            set
            {
                if (value.Trim() != "")
                {
                    m_tableName = value;
                    if (m_className.Trim() == "")
                    {
                        m_className = m_tableName;
                    }
                }
            }
        }
        /// <summary>
        /// 实体对应的类名，当表名没有设定时，使用类名最为表名
        /// </summary>
        public string ClassName
        {
            get { return m_className; }
            set
            {
                if (value.Trim() != "")
                {
                    m_className = value;
                    if (m_tableName.Trim() == "")
                    {
                        m_tableName = m_className;
                    }
                }
            }
        }
        /// <summary>
        /// 实体对应的名称空间，默认为"BRL"
        /// </summary>
        public string NameSpace
        {
            get { return m_nameSpace; }
            set
            {
                if (value.Trim() != "")
                {
                    m_nameSpace = value;
                }
            }
        }
        /// <summary>
        /// 生成的实体是否继承自含有code的基类
        /// </summary>
        public bool HasCode
        {
            get { return m_hasCode; }
            set { m_hasCode = value; }
        }
        /// <summary>
        /// 实体是否缓存表
        /// </summary>
        public bool CacheTable
        {
            get { return m_cacheTable; }
            set { m_cacheTable = value; }
        }
        /// <summary>
        /// 实体是否缓存对象
        /// </summary>
        public int CacheObject
        {
            get { return m_cacheObject; }
            set { m_cacheObject = value; }
        }
        /// <summary>
        /// 不包含固定属性时的用于构造函数中的代码
        /// </summary>
        protected Dictionary<string, string> NotSetColumn
        {
            get
            {
                if (m_notSetColumn == null)
                {
                    m_notSetColumn = new Dictionary<string, string>();
                    //m_notSetColumn.Add("comment", "\t\t\tm_hasComment = false;");
                    //m_notSetColumn.Add("name", "\t\t\tm_hasName = false;");
                    if (m_hasCode)
                    {
                        //m_notSetColumn.Add("code", "\t\t\tm_hasCode = false;");
                    }
                }
                return m_notSetColumn;
            }
        }
        /// <summary>
        /// 包含固定属性时的用于构造函数中的代码
        /// </summary>
        protected Dictionary<string, string> SetColumn
        {
            get
            {
                if (m_setColumn == null)
                {
                    m_setColumn = new Dictionary<string, string>();
                    m_setColumn.Add("ts", "\t\t\tm_hasTS = true;");
                    m_setColumn.Add("guid", "\t\t\tm_hasGuid = true;");
                    m_setColumn.Add("name", "\t\t\tm_hasName = true;");
                    m_setColumn.Add("comment", "\t\t\tm_hasComment = true;");
                    if (m_hasCode)
                    {
                        m_setColumn.Add("code", "\t\t\tm_hasCode = true;");
                    }
                }
                return m_setColumn;
            }
        }

        /// <summary>
        /// 初始化数据库操作对象
        /// </summary>
        protected void InitDB()
        {
            if (m_connStr.Trim() != "")
            {
                m_db = DBFactory.GetDBOP(ConnStr, m_dbType);
            }
        }

        /// <summary>
        /// 是否是固定字段
        /// </summary>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected bool IsFix(DataColumn dc)
        {
            for (int i = 0; i < m_fix.Length; i++)
            {
                if (dc.ColumnName.ToLower().Trim() == m_fix[i] || dc.ColumnName.Trim().Length == 0)
                {
                    return true;
                }
                else if (dc.ColumnName.ToLower().Trim() == "code" && m_hasCode)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 生成属性代码
        /// </summary>
        /// <param name="tp"></param>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected string GetAttExp(string tp, DataColumn dc)
        {
            string columnName = dc.ColumnName;
            string sql = "SELECT value FROM ::fn_listextendedproperty (NULL, 'user', 'dbo', 'table', '" + TableName + "', 'column', default) where objname='" + dc.ColumnName + "'";
            string description = m_db.ExecuteScalar(sql);
            string tmp = "\t\t/// <summary>\n\t\t/// {4}\n\t\t/// </summary>\n";
            tmp += "\t\tpublic {0} {1}{2}\n\t\t{{\n\t\t\tget {{ return m_{3}; }}\n\t\t\tset {{ m_{3} = value; }}\n\t\t}}\n";
            string fst = columnName[0].ToString().ToUpper();
            string rem = columnName.Substring(1);
            return string.Format(tmp, tp, fst, rem, columnName, description);
        }
        /// <summary>
        /// 生成用于获取属性的函数中代码
        /// </summary>
        /// <param name="tp"></param>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected string GetGtpExp(string tp, DataColumn dc)
        {
            string tmp = "\t\t\tm_{0} = this.Get{1}Value(record, \"{0}\");\n";
            return string.Format(tmp, dc.ColumnName, tp);
        }
        /// <summary>
        /// 生成用于填充函数中的代码
        /// </summary>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected string GetFillExp(DataColumn dc)
        {
            string tmp = "\t\t\tm_container.Add(\"{0}\", m_{0}{1});\n";
            if (dc.DataType == typeof(bool))
            {
                return string.Format(tmp, dc.ColumnName, "? 1 : 0");
            }
            return string.Format(tmp, dc.ColumnName, "");
        }

        /// <summary>
        /// 创建BOL对象的C＃代码
        /// </summary>
        public string Create()
        {
            string sql = string.Format("select * from [{0}] where 1=0", m_tableName);
            DataTable dt = m_db.Select(sql).Tables[0];
            StringBuilder sb_res = new StringBuilder();
            StringBuilder sb_fld = new StringBuilder();
            StringBuilder sb_att = new StringBuilder();
            StringBuilder sb_fil = new StringBuilder();
            StringBuilder sb_gtp = new StringBuilder();
            StringBuilder sb_stc = new StringBuilder();

            #region 构造字段相关的代码

            sb_stc.AppendLine(string.Format("\t\tpublic {0}()", m_className));
            sb_stc.AppendLine("\t\t{");
            sb_stc.AppendLine(string.Format("\t\t\tm_tableName = \"{0}\";", m_tableName));

            sb_fil.AppendLine("\t\tprotected override void FillContainer()");
            sb_fil.AppendLine("\t\t{");
            sb_fil.AppendLine("\t\t\tbase.FillContainer();");

            sb_gtp.AppendLine("\t\tpublic override bool GetProperties(System.Data.DataRow record)");
            sb_gtp.AppendLine("\t\t{");
            sb_gtp.AppendLine("\t\t\tif(!base.GetProperties(record))");
            sb_gtp.AppendLine("\t\t\t{");
            sb_gtp.AppendLine("\t\t\t\treturn false;");
            sb_gtp.AppendLine("\t\t\t}");

            for (int i = 0; i < dt.Columns.Count; i++)
            {
                DataColumn dc = dt.Columns[i];
                if (this.IsFix(dc))
                {
                    string column = dc.ColumnName.ToLower();
                    if (NotSetColumn.ContainsKey(column))
                    {
                        NotSetColumn.Remove(column);
                    }
                    if (SetColumn.ContainsKey(column))
                    {
                        sb_stc.AppendLine(SetColumn[column]);
                    }
                    continue;
                }
                sb_fld.Append("\t\tprotected ");
                if (dc.DataType == typeof(int) || dc.DataType == typeof(short))
                {
                    sb_fld.Append("int m_" + dc.ColumnName + " = 0;\n");
                    sb_att.Append(this.GetAttExp("int", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("Int", dc));
                }
                else if (dc.DataType == typeof(string))
                {
                    sb_fld.Append("string m_" + dc.ColumnName + " = string.Empty;\n");
                    sb_att.Append(this.GetAttExp("string", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("String", dc));
                }
                else if (dc.DataType == typeof(double))
                {
                    sb_fld.Append("double m_" + dc.ColumnName + " = 0.0;\n");
                    sb_att.Append(this.GetAttExp("double", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("Double", dc));
                }
                else if (dc.DataType == typeof(decimal))
                {
                    sb_fld.Append("double m_" + dc.ColumnName + " = 0.0;\n");
                    sb_att.Append(this.GetAttExp("double", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("Double", dc));
                }
                else if (dc.DataType == typeof(bool))
                {
                    sb_fld.Append("bool m_" + dc.ColumnName + " = false;\n");
                    sb_att.Append(this.GetAttExp("bool", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("Bool", dc));
                }
                else if (dc.DataType == typeof(DateTime))
                {
                    sb_fld.Append("DateTime m_" + dc.ColumnName + " = DateTime.MinValue;\n");
                    sb_att.Append(this.GetAttExp("DateTime", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("Date", dc));
                }

                else if (dc.DataType == typeof(byte[]))
                {
                    sb_fld.Append("byte[] m_" + dc.ColumnName + " = new byte[0];\n");
                    sb_att.Append(this.GetAttExp("byte[]", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.Append(this.GetGtpExp("ByteArray", dc));
                }
                else if (dc.DataType == typeof(Guid))
                {
                    sb_fld.Append("Guid m_" + dc.ColumnName + " = Guid.NewGuid();\n");
                    sb_att.Append(this.GetAttExp("Guid", dc));
                    sb_fil.Append(this.GetFillExp(dc));
                    sb_gtp.AppendFormat("\t\t\tm_{0} = (System.Guid)record[\"{0}\"];\n", dc.ColumnName);
                }
                else
                {
                    Console.WriteLine(dc.ColumnName + " is " + dc.DataType.ToString());
                }
            }
            sb_fil.AppendLine("\t\t}");
            sb_gtp.AppendLine("\t\t\treturn true;");
            sb_gtp.AppendLine("\t\t}");

            foreach (string str in NotSetColumn.Values)
            {
                sb_stc.AppendLine(str);
            }

            if (m_cacheTable)
            {
                sb_stc.AppendLine("\t\t\tm_tblCacheManager.IsEnable = true;");
            }
            if (m_cacheObject > 0)
            {
                sb_stc.AppendLine(string.Format("\t\t\tm_objCacheManager.Size = {0};", m_cacheObject));
            }
            sb_stc.AppendLine("\t\t}");

            #endregion

            sb_res.AppendLine("using System;");
            sb_res.AppendLine("using System.Data;");
            sb_res.AppendLine("using System.Collections.Generic;");
            sb_res.AppendLine();
            sb_res.AppendLine(string.Format("namespace {0}", NameSpace));
            sb_res.AppendLine("{");
            sb_res.AppendLine(string.Format("\tpublic partial class {0} : JWFW.BOL.Base{1}Entity", m_className, m_hasCode ? "Config" : ""));
            sb_res.AppendLine("\t{");
            sb_res.AppendLine(sb_stc.ToString());
            sb_res.AppendLine(sb_fld.ToString());
            sb_res.AppendLine(sb_att.ToString());
            sb_res.AppendLine(sb_fil.ToString());
            sb_res.AppendLine(sb_gtp.ToString());
            sb_res.AppendLine("\t}");
            sb_res.AppendLine("}");
            Console.WriteLine(sb_res);
            return sb_res.ToString();
        }


        protected void Test()
        {
            ConnStr = "server=localhost;uid=sa;password=password123$;database=jwgf";
            TableName = "t_trial";
            ClassName = "Trial";
            NameSpace = "BaseServer.BRL";
            HasCode = true;
            CacheTable = true;
            CacheObject = 0;
            this.Create();
        }
    }
}
